package com.example.sudoku;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.os.Handler;

import java.io.IOException;
import java.util.Locale;

public class SudokuView extends View {
    
    // 用于跳转至MainActivity
    private final Context mContext;
    private final Intent intent;
    // 定义一个对话框
    private final AlertDialog.Builder builder;

    // 开关属性
    private final RectF Right, Left, Center;

    // 计时器
    private final Handler handler;
    private final Runnable timeRunnable;
    // 时间:毫秒
    private long second = 0;
    private long lastSecond = 0;
    // 格式化后的时间
    private String timeString;

    // 单元格高度和宽度
    private float height;
    private float width;

    // 获取点击具体信息
    private int x = -1;
    private int y = -1;
    // 点击位置
    private String click;
    // 判断标志
    private final Boolean flag;
    // 难度
    private final int game_mode;

    // 定义画笔
    private final Paint backgroundPaint, blackPaint, whitePaint, darkPaint, lightPaint;
    private final Paint greenNumberPaint, blackNumberPaint, blueNumberPaint, textPaint;
    private final Paint shapePaint, circlePaint;

    // 定义每个单元格坐标
    private final float [] baseX = new float[9];
    private final float [] baseY = new float[9];

    //    宏定义，设定X和Y方向上的偏移
    public static final float offsetX = 100;
    public static final float offsetY = 150;

    //    构造函数
    public SudokuView(Context context, int mode, int help) {
        super(context);

        // 初始化，获得context即GameActivity.this值
        mContext = context;
        intent= new Intent();
        // 实例化一个对话框
        builder = new AlertDialog.Builder(context);

        // 计时
        handler = new Handler();
        timeRunnable = new Runnable() {
            @Override
            public void run() {
                // 更新时间
                second += 1000;
                // 更新屏幕
                updateTime();
                // 递归调用自身
                handler.postDelayed(this, 1000);
            }
        };
        // 开始计时
        startTime();
        // 初始化开始时间
        timeString = "00:00:00";

        // 确定标志的值
        if(help == 1) flag = Boolean.TRUE;
        else flag = Boolean.FALSE;

        game_mode = mode;

        Right = new RectF();
        Left = new RectF();
        Center = new RectF();

        // 初始化点击位置
        click = "";

//        设置画笔颜色和宽度
        backgroundPaint = new Paint();
        backgroundPaint.setColor(getResources().getColor(R.color.Sudoku_background));

        blackPaint = new Paint();
        blackPaint.setColor(getResources().getColor(R.color.Sudoku_black));
        blackPaint.setStrokeWidth(6);

        whitePaint = new Paint();
        whitePaint.setColor(getResources().getColor(R.color.Sudoku_white));
        whitePaint.setStrokeWidth(5);

        darkPaint = new Paint();
        darkPaint.setColor(getResources().getColor(R.color.Sudoku_dark));
        darkPaint.setStrokeWidth(5);

        lightPaint = new Paint();
        lightPaint.setColor(getResources().getColor(R.color.Sudoku_light));
        lightPaint.setStrokeWidth(5);

//        数字画笔
        greenNumberPaint = new Paint();
        greenNumberPaint.setColor(getResources().getColor(R.color.Sudoku_green));
        greenNumberPaint.setStyle(Paint.Style.FILL);       //实心
        greenNumberPaint.setTextAlign(Paint.Align.CENTER);   //居中对齐
        greenNumberPaint.setAntiAlias(true); // 抗锯齿

        blackNumberPaint = new Paint();
        blackNumberPaint.setColor(getResources().getColor(R.color.Sudoku_black));
        blackNumberPaint.setStyle(Paint.Style.FILL);       //实心
        blackNumberPaint.setTextAlign(Paint.Align.CENTER);   //居中对齐
        blackNumberPaint.setAntiAlias(true); // 抗锯齿

        blueNumberPaint = new Paint();
        blueNumberPaint.setColor(getResources().getColor(R.color.Sudoku_blue));
        blueNumberPaint.setStyle(Paint.Style.FILL);       //实心
        blueNumberPaint.setTextAlign(Paint.Align.CENTER);   //居中对齐
        blueNumberPaint.setAntiAlias(true); // 抗锯齿

//        文本画笔
        textPaint = new Paint();
        textPaint.setColor(getResources().getColor(R.color.Sudoku_black));
        textPaint.setStyle(Paint.Style.FILL);       //实心
        textPaint.setTextAlign(Paint.Align.CENTER);   //居中对齐
        textPaint.setAntiAlias(true); // 抗锯齿

//        开关画笔
        shapePaint = new Paint();
        shapePaint.setStyle(Paint.Style.FILL);       //实心
        shapePaint.setAntiAlias(true); // 抗锯齿
        shapePaint.setStrokeWidth(0);

        circlePaint = new Paint();
        circlePaint.setColor(getResources().getColor(R.color.Sudoku_white));
        circlePaint.setStyle(Paint.Style.FILL);       //实心
        circlePaint.setAntiAlias(true); // 抗锯齿
    }

//        划分成九宫格
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//        计算每个单元格宽度
        this.width = (w - 2 * offsetX) / 9f;
        this.height = (h - 4 * offsetY) / 9f;

//        计算每一个单元格坐标
        float half_width = width / 2;
        for(int i = 0; i < 9; i++){
            // 确保居中显示
            baseX[i] = offsetX + i * width + half_width;
            baseY[i] = offsetY + i * height + 0.8f * height;
        }

        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 绘制背景
        canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);

        // 根据click判断点击事件
        if(click.equals("")) {
            // 重置选中单元格
            x = y = -1;
        }
        else {
            int num = click.charAt(1) - 'A';
            // 选中可填入数字
            if(num == 0){
                // 获取选中的数字
                num = click.charAt(0) - '0';
                if(x >= 0 && x <= 8 && y >= 0 && y <= 8)
                    // 符合要求，填入数字
                    // flag为true表示提供判断，flag为false表示不提供
                    CreateBoard.insertNum(num, y, x, flag);
            }
            // 选中功能按钮
            else if(num == 1){
                // 计算偏移值
                num = click.charAt(0) - '0';
                num = num - num % 2;
                // 退出按钮
                if(num == 0){
                    // 暂停计时器
                    stopTime();
                    // 重置选中单元格
                    x = y = -1;
                    // 弹出对话框
                    builder.setMessage("确定退出游戏吗？")
                    // lambda简化
                    // 设定积极按钮及重写OnClick函数
                    .setPositiveButton("确定", (dialog, which) -> {
                        click = "";
                        // 跳转到MainActivity
                        // 设置跳转的源和目的Activity
                        intent.setClass(mContext, MainActivity.class);
                        // context跳转需要开始新的task，因此需要添加Flag值
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        // 跳转
                        mContext.startActivity(intent);
                        // 关闭GameActivity
                        ((Activity)mContext).finish();
                    })
                    // 设定消极按钮及重写OnClick函数
                    .setNegativeButton("取消", (dialog, which) -> {
                        click = "";
                        // 开始计时器
                        startTime();
                    })
                    .show();
                }
                // 清除按钮
                else if(num == 2){
                    // 清除当前单元格数字
                    if(x >= 0 && x <= 8 && y >= 0 && y <= 8)
                        CreateBoard.clear_one(y, x);
                }
                // 重置按钮
                else if(num == 4){
                    click = "";
                    // 暂停计时器
                    stopTime();
                    // 重置选中单元格
                    x = y = -1;
                    // 弹出对话框
                    builder.setMessage("确定重置数独吗？")
                    // lambda简化
                    // 设定积极按钮及重写OnClick函数
                    .setPositiveButton("确定", (dialog, which) -> {
                        // 重置为初始数独
                        CreateBoard.clear_all();
                        // 开始计时器
                        startTime();
                        invalidate();
                    })
                    // 设定消极按钮及重写OnClick函数
                    .setNegativeButton("取消", (dialog, which) -> {
                        // 开始计时器
                        startTime();
                    })
                    .show();
                }
                // 提交按钮
                else if(num == 6){
                    click = "";
                    // 暂停计时器
                    stopTime();
                    // 重置选中单元格
                    x = y = -1;
                    // 弹出对话框
                    // 设定输出信息
                    builder.setMessage("确定提交数独吗？")
                    // 设定积极按钮及重写OnClick函数
                    .setPositiveButton("确定", (dialog, which) -> {
                        // 提交数独结果
                        int ret = CreateBoard.check_board();
                        // 存储输出信息
                        String submit = "";
                        switch(ret) {
                            // 结果正确
                            case 1:
                                // 保存成功通过信息
                                int i = (flag) ? 1 : 0;
                                save.save_file((int)second/1000, game_mode, i);
                                submit = "恭喜成功通过! 用时 " + timeString + " 得分: "
                                        + save.return_score((int)second/1000, game_mode, i)
                                        + "\n请点击确定回到开始界面";
                                // 弹出对话框
                                // 设定输出信息
                                builder.setMessage(submit)
                                .setPositiveButton("确定", (dialog1, which1) -> {
                                    // 跳转到MainActivity
                                    // 设置跳转的源和目的Activity
                                    intent.setClass(mContext, MainActivity.class);
                                    // context跳转需要开始新的task，因此需要添加flag值
                                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                    // 跳转
                                    mContext.startActivity(intent);
                                    // 关闭GameActivity
                                    ((Activity)mContext).finish();
                                })
                                .setNegativeButton("", (dialog1, which1) -> {
                                })
                                .show();
                                break;
                            // 结果错误
                            case 0:
//                                if(submit.equals(""))
                                    submit = "很遗憾，数独错误！";
                                // 弹出对话框
                                // 设定输出信息
                                builder.setMessage(submit)
                                .setNegativeButton("退出游戏", (dialog1, which1) -> {
                                    // 跳转到MainActivity
                                    // 设置跳转的源和目的Activity
                                    intent.setClass(mContext, MainActivity.class);
                                    // context跳转需要开始新的task，因此需要添加flag值
                                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                    // 跳转
                                    mContext.startActivity(intent);
                                    // 关闭GameActivity
                                    ((Activity)mContext).finish();
                                })
                                .setPositiveButton("继续游戏", (dialog1, which1) -> {
                                    // 开始计时器
                                    startTime();
                                })
                                .show();
                                break;
                        }
                    })
                    // 设定消极按钮及重写OnClick函数
                    .setNegativeButton("取消", (dialog, which) -> {
                        // 开始计时器
                        startTime();
                    })
                    .show();
                }
            }
            // 绘制选中单元格
            else{
                // 获取选中单元格坐标
                x = click.charAt(0) - '1';
                y = click.charAt(1) - '1';
            }
        }

//        绘制开关
        // 计算中间矩形的位置
        Center.left = offsetX + 7 * width;
        Center.right = offsetX + 8 * width + width / 2;
        Center.top = offsetY - 115;
        Center.bottom = offsetY - 35;

        // 计算左右半圆半径
        float radius = (Center.bottom - Center.top) / 2;

        // 设定左半圆的位置
        Left.left = Center.left - radius;
        Left.right = Center.left + radius;
        Left.top = Center.top;
        Left.bottom = Center.bottom;

        // 设定右半圆的位置
        Right.left = Center.right - radius;
        Right.right = Center.right + radius;
        Right.top = Center.top;
        Right.bottom = Center.bottom;

        // 设置文本画笔
        textPaint.setTextSize(1.5f * radius);         //高度

        // 开关打开，帮助筛选
        if(flag) {
            // 计算右半圆的圆心坐标
            float rx = Center.right;
            float ry = (Center.top + Center.bottom) / 2;
            shapePaint.setColor(getResources().getColor(R.color.Sudoku_green));
            //画矩形
            canvas.drawRect(Center, shapePaint);
            //画左边的半圆
            canvas.drawArc(Left, -90, -180, false, shapePaint);
            //画右边的半圆
            canvas.drawArc(Right, -90, 180, false, shapePaint);
            // 绘制圆点
            canvas.drawCircle(rx, ry, radius, circlePaint);
            // 绘制文字
            canvas.drawText("开启", offsetX + 7 * width + width / 2, ry + 0.6f * radius ,textPaint);
        }
        // 开关关闭，禁用筛选
        else {
            // 计算左半圆的圆心坐标
            float lx = Center.left;
            float ly = (Center.top + Center.bottom) / 2;
            shapePaint.setColor(getResources().getColor(R.color.Sudoku_dark));
            //画矩形
            canvas.drawRect(Center, shapePaint);
            //画左边的半圆
            canvas.drawArc(Left, -90, -180, false, shapePaint);
            //画右边的半圆
            canvas.drawArc(Right, -90, 180, false, shapePaint);
            // 绘制圆点
            canvas.drawCircle(lx, ly, radius, circlePaint);
            // 绘制文字
            canvas.drawText("关闭", offsetX + 8 * width, ly + 0.6f * radius ,textPaint);
        }

        // 设置数字画笔
        greenNumberPaint.setTextSize(0.75f * height);   //高度
        blackNumberPaint.setTextSize(0.75f * height);   //高度
        blueNumberPaint.setTextSize(0.75f * height);    //高度

        // 设置文本画笔
        textPaint.setTextSize(0.6f * height);         //高度

        // 绘制计时的时间
        canvas.drawText(timeString, 0.5f * getWidth(), 0.7f * offsetY, textPaint);

//        判断是否绘制高亮
        if(x >= 0 && x <= 8 && y >= 0 && y <= 8) {
            // 绘制纵向高亮
            canvas.drawRect(offsetX + x * width, offsetY, offsetX + (x + 1) * width, offsetY + 9 * height, lightPaint);
            // 绘制横向高亮
            canvas.drawRect(offsetX, offsetY + y * height, offsetX + 9 * width, offsetY + (y + 1) * height, lightPaint);
            // 绘制九宫格高亮
            canvas.drawRect(offsetX + (x - x % 3) * width, offsetY + (y - y % 3) * height, offsetX + (x - x % 3 + 3) * width, offsetY + (y - y % 3 + 3) * height, lightPaint);
            // 绘制选中高亮
            canvas.drawRect(offsetX + x * width, offsetY + y * height, offsetX + (x + 1) * width, offsetY + (y + 1) * height, darkPaint);
            // 绘制选中数字
            if (CreateBoard.board2[y][x] != 0)
                canvas.drawText(String.valueOf(CreateBoard.board2[y][x]), baseX[x], baseY[y], greenNumberPaint);
        }

//        绘制九宫格
        for (int i = 0; i < 9; i++) {
            // 绘制单元格横线，画紧邻的两条线
            canvas.drawLine(offsetX, offsetY + i * height, getWidth() - offsetX, offsetY + i * height, lightPaint);
            canvas.drawLine(offsetX, offsetY + i * height + 1, getWidth() - offsetX, offsetY + i * height + 1, whitePaint);
            // 绘制单元格竖线，画紧邻的两条线
            canvas.drawLine(offsetX + i * width, offsetY, offsetX + i * width, getHeight() - 3 * offsetY, lightPaint);
            canvas.drawLine(offsetX + i * width + 1, offsetY, offsetX + i * width + 1, getHeight() - 3 * offsetY, whitePaint);
        }
        for(int i = 0; i <= 9; i = i + 3) {
            // 绘制边界线，横线
            canvas.drawLine(offsetX, offsetY + i * height, getWidth() - offsetX, offsetY + i * height, blackPaint);
            // 绘制边界线，竖线
            canvas.drawLine(offsetX + i * width, offsetY, offsetX + i * width, getHeight() - 3 * offsetY, blackPaint);

        }

//        绘制数字
        // 按行绘制
        for(int i = 0; i < 9; i++){
            for(int j = 0; j < 9; j++){
                // 跳过选中单元格数字
                if(x >= 0 && x <= 8 && y >= 0 && y <= 8)
                    if(i == y && j == x)
                        continue;
                // 初始数独布局用黑色
                if(CreateBoard.memorize[i][j] != 0) {
                    // 绘制数字
                    canvas.drawText(String.valueOf(CreateBoard.board2[i][j]), baseX[j], baseY[i], blackNumberPaint);
                }
                // 用户填写数字用蓝色
                else if(CreateBoard.board2[i][j] != 0) {
                    // 绘制数字
                    canvas.drawText(String.valueOf(CreateBoard.board2[i][j]), baseX[j], baseY[i], blueNumberPaint);
                }
                // 跳过未填写数字的单元格
            }
        }

//         绘制可以选择填入的数字
        // flag为真，提供判断可填入数字的功能
        if(flag) {
            // 获取可以选择填入的数字
            int [] check = CreateBoard.check(y, x);
            for(int i = 0; i < 9; i++){
                // 跳过不可填入的数字
                if(check[i+1] == 0) continue;
                // 绘制可填入数字
                canvas.drawText(String.valueOf(i+1), baseX[i], baseY[8] + 2 * height, greenNumberPaint);
            }
        }
        // flag为假，不提供筛选
        else {
            // 绘制填入数字1-9
            for(int i = 0; i < 9; i++){
                canvas.drawText(String.valueOf(i+1), baseX[i], baseY[8] + 2 * height, greenNumberPaint);
            }
        }


//        绘制按钮
        canvas.drawText("退出", baseX[1], baseY[8] + 3 * height, textPaint);
        canvas.drawText("清除", baseX[3], baseY[8] + 3 * height, textPaint);
        canvas.drawText("重置", baseX[5], baseY[8] + 3 * height, textPaint);
        canvas.drawText("提交", baseX[7], baseY[8] + 3 * height, textPaint);

    }

//    点击事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        // 点击动作
        if(event.getAction() != MotionEvent.ACTION_DOWN) {
            performClick();
            return super.onTouchEvent(event);
        }

        // 获取点击坐标
        float getx = event.getX();
        float gety = event.getY();

        // 游戏中不允许修改开关的功能
//        if(getx > Left.left && getx < Right.right && gety > Center.top && gety < Center.bottom) {
//            // 修改开关状态
//            flag = !flag;
//            // 重置选中单元格
//            x = y = -1;
//            invalidate();
//        }

        // 点击无效
        if(getx < offsetX || gety < offsetY || getx > getWidth() - offsetX)
            return super.onTouchEvent(event);

        // 计算相对偏移
        int X = (int)((getx - offsetX) / width);
        int Y = (int)((gety - offsetY) / height);

        // 点击九宫格内
        if(X < 9 && Y < 9) {
            // 存储单元格位置
            click = String.valueOf(X * 10 + Y + 11);
            invalidate();
        }
        // 点击可填入数字
        else if(X < 9 && Y == 10) {
            // 存储点击选择数字
            click = String.valueOf(X + 1) + 'A';
            invalidate();
        }
        // 点击功能按钮
        else if(X < 9 && Y == 11) {
            // 存储点击按钮
            click = String.valueOf(X) + 'B';
            invalidate();
        }

        return super.onTouchEvent(event);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }

    // 更新时间
    public void updateTime() {
        // 得到时间：秒
        long time = second / 1000;
        // 换算成小时:分钟:秒
        int s = (int) (time % 60);
        int m = (int) (time / 60) % 60;
        int h = (int) (time / 3600) % 60;
        // 更新用于输出的时间字符串
        timeString = String.format(Locale.getDefault(), "%02d:%02d:%02d", h, m, s);
        // 更新屏幕
        invalidate();
    }

    // 停止计时
    public void stopTime() {
        // 停止计时器
        handler.removeCallbacks(timeRunnable);
        // 保存时间
        lastSecond = second;
    }

    // 开始计时
    public void startTime() {
        // 恢复时间
        second = lastSecond;
        // 开始计时器
        handler.postDelayed(timeRunnable, 1000);
    }
}